package cn.itcast.controller;

import cn.itcast.domain.system.FeedBack;
import cn.itcast.domain.system.Module;
import cn.itcast.domain.system.User;
import cn.itcast.service.system.FeedService;
import cn.itcast.service.system.ModuleService;
import cn.itcast.service.system.UserService;
import cn.itcast.utils.HttpUtils;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.UsernamePasswordToken;
import org.apache.shiro.crypto.hash.Md5Hash;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.util.StringUtils;
import org.springframework.web.bind.annotation.RequestMapping;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;
import java.util.Date;
import java.util.List;
import java.util.Map;

@Controller
public class LoginController{

    @Autowired
    private HttpServletRequest request;
    @Autowired
    private HttpSession session;
    @Autowired
    private ModuleService moduleService;

    @Autowired
    private UserService userService;
    @Autowired
    private FeedService feedService;

    @RequestMapping(value = "/login",name = "登陆判断")
    public String login(String email,String password) {

        //1.email和password不能为空
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(password)) {

            //有一个为空，在页面中进行错误提示
            //向request域中存入错误信息
            request.setAttribute("error", "邮箱或密码为空···");
            //重定向到登陆页面
            return "forward:/login.jsp";
        }

        /**
         * info，仅仅是当前用户数据算出来的值，
         * login会根据登陆信息创建一个token，就是login方法的参数，
         * shiro会校验info和token
         *
         * 例如：一个人要做火车，而必须要有火车票
         *       坐车前，必须先买票，（车站根据个人信息打印车票）---token  坐车的凭证
         *       坐车.login(车票)
         *       shiro相当于检票机，校验身份，系统中是否有该用户车票信息(info)和车票(token)
         * */
        //把页面上输入的明文密码转成密文
        password = new Md5Hash(password,email,2).toString();
        //使用shiro的认证方式 1.创建令牌  2.获取主题  3.开始认证
        //1.创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken(email, password);
        //2.获取主题
        Subject subject = SecurityUtils.getSubject();
        //开始认证
        try {

            subject.login(token);
           /**
            * 执行到这句代码时，进入 DelegatingSubject implements Subject的 login方法
             *  public void login(AuthenticationToken token) throws AuthenticationException {
                   this.clearRunAsIdentitiesInternal();
                   Subject subject = this.securityManager.login(this, token);

            DelegatingSubject的login方法-----》AuthenticatingRealm 的getAuthenticationInfo方法（比较token、info是否为空）······
             一路向下追踪源码，比较先info和token是否为空，都不为空，再判断subject是否为空，
             均不为空，再层层返回，确定所有信息都匹配，结束subject.login(token);
            继续往下执行 ------进入SaasRealm中，进行认证，返回SimpleAuthenticationInfo对象
            ----跳出代码块，继续向下执行
            }
            * */

        } catch (AuthenticationException e) {
            e.printStackTrace();
            request.setAttribute("error","邮箱或者密码错误");
            return "forward:login.jsp";
        }

        //获取主角：当前登陆人
        User user = (User) subject.getPrincipal();
        //把当前登陆人放入到session
        session.setAttribute("loginUser",user);
        List<Module> moduleList = moduleService.findModuleListByUser(user);
        session.setAttribute("modules",moduleList);

        //当用户登陆时就查询所收到的邮件总个数，存放到session域中
        List<FeedBack> list = null;
        //User loginUser =(User) session.getAttribute("loginUser");
        //企业管理员---根据公司id查询
        if (user.getDegree()==1){

            list = feedService.findTotalMessageByCompanyId(user.getCompanyId(),user.getEmail());
        }
        //SaaS管理员---根据degree查询
        if (user.getDegree()==0){

            list = feedService.findTotalMessageByDegree(1);
        }
        session.setAttribute("list",list);
        //设置用户登录时间
        Date loginDate = new Date();
        session.setAttribute("loginDate",loginDate);
        return "home/main";

    }

        /*//2.根据email查询用户
        User user = userService.findByEmail(email);
        if (user==null){

            request.setAttribute("error","邮箱输入错误，请重新输入···");
            //重定向到登陆页面
            return "forward:/login.jsp";
        }
        else {

            //3.email正确--检查密码
            //需要先把页面上的明文密码进行加盐加密，再和数据库中的密码进行比较
            String password_page = new  Md5Hash(password,user.getEmail(),2).toString();
            if (!user.getPassword().equals(password_page)){

                request.setAttribute("error","密码输入错误，请重新输入···");
                //重定向到登陆页面
                return "forward:/login.jsp";
            }

        }


        //4.email和password都正确，跳转到home/main页面
        session.setAttribute("loginUser",user);

        //根据登陆用户查询模块信息
        List<Module> moduleList = moduleService.findModuleListByUser(user);
        session.setAttribute("modules",moduleList);
        return "home/main";
    }*/

    @RequestMapping(value = "/log",name = "微信进主页面方法")
    public String log(){
        return "home/main";
    }


    //微信登陆
    @RequestMapping(value = "/weixinlogin",name = "进入微信登录方法")
    public String weixinlogin(String code,String state) {
        // 判断
        if (code == null) {
            System.out.println("用户未授权...");
        }
        //获取到了code值，回调没有问题
        //1.根据code获取access_token和openId
        String atUtl = "https://api.weixin.qq.com/sns/oauth2/access_token" + "?code=" + code + "&appid=wx3bdb1192c22883f3&secret=db9d6b88821df403e5ff11742e799105&grant_type=authorization_code";
        Map<String, Object> map1 = HttpUtils.sendGet(atUtl);

        Object access_token = map1.get("access_token");
        Object openid = map1.get("openid").toString();
        if (access_token == null && openid == null) {
            System.out.println("用户未登录...");
        }
        //2.根据access_token和openId获取微信用户信息
        /*可通过获取用户基本信息中的unionid来区分用户的唯一性，
        因为只要是同一个微信开放平台帐号下的移动应用、网站应用和公众帐号，
        用户的unionid是唯一的。换句话说，同一用户，对同一个微信开放平台下的不同应用，unionid是相同的。
        * */
        String wxurl = "https://api.weixin.qq.com/sns/userinfo?access_token=" + access_token + "&openid=" + openid;
        Map<String, Object> map2 = HttpUtils.sendGet(wxurl);
        Object unionid = map2.get("unionid");
        String unionid_s = unionid.toString();
        User user1 = userService.finbByUnionid(unionid_s);
        if (user1 == null) {
            //微信绑定页面
            request.setAttribute("unionid", unionid_s);
            return "forward:email.jsp";
        }
        //创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken(user1.getEmail(), user1.getPassword());
        //获取主题
        Subject subject = SecurityUtils.getSubject();
        //开始认证
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            //e.printStackTrace();
            request.setAttribute("error","邮箱或者密码错误");
            return "forward:login.jsp";
        }
        //获取主角
        User user = (User) subject.getPrincipal();//从shiro中获取当前登录人
        //把登录人放入到session
        session.setAttribute("loginUser",user);
        List<Module> moduleList = moduleService.findModuleListByUser(user);
        session.setAttribute("modules",moduleList);
        return "redirect:log.do";
    }


    //微信登陆之邮箱绑定
    @RequestMapping(value = "/emailAdd",name = "微信第一次扫码进入绑定邮箱方法")
    public String emailAdd(String email,String password,String unionid) {
        //0.email和password不能为空
        if (StringUtils.isEmpty(email) || StringUtils.isEmpty(password)) {
            request.setAttribute("unionid",unionid);
            request.setAttribute("error","邮箱或密码不能为空");
            //重定向：相当于让浏览器重新发起了一次请求，之前的request和response丢失了
            return "forward:email.jsp"; //请求转发
        }
        //使用shiro的认证方式：1.创建令牌 2.获取主题 3.开始认证
        password = new Md5Hash(password, email, 2).toString(); //把页面上输入的明文的密码转成密文的
        //创建令牌
        UsernamePasswordToken token = new UsernamePasswordToken(email, password);
        //获取主题
        Subject subject = SecurityUtils.getSubject();
        //开始认证
        try {
            subject.login(token);
        } catch (AuthenticationException e) {
            //e.printStackTrace();
            request.setAttribute("error","邮箱或者密码错误");
            request.setAttribute("unionid",unionid);
            return "forward:email.jsp";
        }
        User user_email = userService.findByEmail(email);
        if (!StringUtils.isEmpty(user_email.getWxunionid())) {
            request.setAttribute("error","该账户已被绑定,请解绑后重试!");
            request.setAttribute("unionid",unionid);
            return "forward:email.jsp";
        }
        User user_wx = new User();
        user_wx.setId(user_email.getId());
        user_wx.setWxunionid(unionid);
        userService.update(user_wx);
        //获取主角
        User user = (User) subject.getPrincipal();//从shiro中获取当前登录人
        //把登录人放入到session
        User us = userService.findById(user.getId());
        session.setAttribute("loginUser",us);
        List<Module> moduleList = moduleService.findModuleListByUser(user);
        session.setAttribute("modules",moduleList);
        return "redirect:log.do";
    }

    @RequestMapping(value = "/wxdl",name="微信解绑")
    public String wxdl(){
        //获取主题
        Subject subject = SecurityUtils.getSubject();
        //获取主角
        User user = (User) subject.getPrincipal();//从shiro中获取当前登录人
        User user_new = new User();
        user_new.setId(user.getId());
        user_new.setWxunionid(null);
        userService.update(user_new);
        User us = userService.findById(user.getId());
        //把登录人放入到session
        session.setAttribute("loginUser",us);
        List<Module> moduleList = moduleService.findModuleListByUser(user);
        session.setAttribute("modules",moduleList);
        return "home/main";
    }


    //退出
    @RequestMapping(value = "/logout",name="退出当前帐户")
    public String logout(){
        //退出当前登录账户
        //如果不声明shiro进行退出，shiro会认为当前用户还未退出，仍能查询信息
        SecurityUtils.getSubject().logout();
        return "forward:login.jsp";
    }

    @RequestMapping(value = "/home")
    public String home(){

        return "home/home";
    }




}
